/**
  * @file       Fingervein.c
  * @brief      指静脉组件
  * @copyright  Copyright (c) 2020~2030 ShenZhen Dxtc Tech. Co., Ltd.
  * All rights reserved.
  * @version    V1.0
  * @author     Liangtao
  * @date       2022-06-21 14:52:09
  * @note       鼎新同创·智能锁
  *
  *****************************************************************************/

 #if defined(FINGERVEIN_SUPPORT)

#include "component.h"
#include "device.h"
#include "fingervein_ota.h"
#include "cycfg_pins.h"

#define FINGERVEIN_DEBUG

/* debug print interface */
#if defined(FINGERVEIN_DEBUG)
    #define FINGERVEIN_TASK_DEBUG_LOG(format, ...) printf( "[fvn.c] " format, ##__VA_ARGS__)
    #define __FINGERVEIN_TASK_DEBUG_LOG(format, ...) printf( "[fvn.c] "  format, ##__VA_ARGS__)
#else
	#define FINGERVEIN_TASK_DEBUG_LOG(format, ...)
	#define __FINGERVEIN_TASK_DEBUG_LOG(format, ...)
#endif

#define FINGERVEIN_TASK_LOG(format, ...) printf(C_LIGHT_CYAN "[fvn.c] " format C_NONE, ##__VA_ARGS__)
#define __FINGERVEIN_TASK_LOG(format, ...) printf(C_LIGHT_CYAN "[fvn.c] " format C_NONE, ##__VA_ARGS__)

/* 定义虚拟硬件接口 */
#if defined(FINGERVEIN_EN_PORT)
	#define VHW_PIN_FINGERVEIN_POWER 			vPIN_C27		//Fingervein-power,单独IO口控制，(901VP，指静脉代替指纹)
#else
	#define VHW_PIN_FINGERVEIN_POWER 			vPIN_C28		//Fingervein-power,595控制，(K8603，指静脉与指纹共存)
#endif
#define IRQ_VHW_FINGERVEIN                 	vPIN_I17
#define VHW_UART_FINGERVEIN 				vUART_7			


/* 指静脉事件*/
#define EVENT_FINGERVEIN_PROTOCOL          	(0X00000001)					//处理指静脉串口协议事件
#define EVENT_SYNC_WITH_MODULE 				(0X00000040)	  				//指静脉上电后的同步握手事件
#define EVENT_OTA_START 					(0X00000080)	  				//指静脉OTA事件；


/* Fingervein power control */
#define FINGERVEIN_MODULE_POWER_ON  Device_Write(VHW_PIN_FINGERVEIN_POWER, NULL, 0, 1)
#define FINGERVEIN_MODULE_POWER_OFF Device_Write(VHW_PIN_FINGERVEIN_POWER, NULL, 0, 0)


#define FINGERVEIN_OPERATE_RINGBUFF_NUM 3	                        	/* 与指静脉模块握手命令环形缓存队列深度 */
#define FINGERVEIN_TX_RINGBUFF_NUM 10	                        		/* 发送命令环形缓存队列深度 */
#define FINGERVEIN_RX_RINGBUFF_NUM 500	                        		/* 接收命令环形缓存队列深度 */
#define FINGERVEIN_RX_RINGBUFF_SIZE 1	                        		/* 接收命令环形队列缓存单个消息大小 */
#define FINGERVEIN_OTA_RINGBUFF_NUM 4500								/* OTA升级环形队列缓存队列深度 */
#define FINGERVEIN_OTA_RINGBUFF_SIZE 1									/* OTA升级环形队列缓存队列单个消息大小 */

#define PROTOCOL_RESEND_TIMES          3									/* 指静脉指令超时重发次数 */


static RingBufferHandle_t fingerveinTx_rbHandle = NULL;    				/* 发送循环队列句柄 */
static RingBufferHandle_t fingerveinRx_rbHandle = NULL;		  			/* 指静脉串口接收数据的队列句柄 */
static RingBufferHandle_t operate_rbHandle = NULL;      			   /* 与指静脉模块握手操作循环队列句柄 */
static RingBufferHandle_t ota_rbHandle = NULL;      			   		/* 指静脉OTA升级队列句柄 */

#define SWAP16(n) ((((uint16_t)(n) >> 8) & 0x00FF) | (((uint16_t)(n) << 8) & 0xFF00))

/* 消息回调函数类型 */
typedef void (*FingerveinMessageCallback_fun_t)(uint8_t cmd, uint8_t result, uint8_t *data, uint8_t len);

/* 回调函数 */
static FingerveinMessageCallback_fun_t pCmdCallback = NULL;


typedef enum
{
	FVN_OTA_INIT,										//初始状态
	FVN_OTA_WAIT_CMD_ACK,								//MCU等待模组OTA指令的ACK回复；
	FVN_OTA_SENDING_SECTION_FILE,						//MCU正在发送分段文件数据；
	FVN_OTA_SEND_SECTION_FILE_FINISH,					//MCU发送分段文件数据完成，等待模组回复；
	FVN_OTA_SEND_ALL_FILE_FINISH,						//MCU发送整个文件数据完成，等待模组回复；
}FingerveinOtaProcess_enum_t;


/* 指静脉初始化标志 */
static FlagStatus fingervein_Init_Flag = RESET;

/* 指静脉模组本身上电初始化握手成功标志，此时MCU已收到指静脉上报的0X55信号 */
static FlagStatus module_Ready_Flag = RESET;

/* 指静脉模块上电标志 */ 
static FlagStatus module_PowerOn_Flag = RESET;

/* 指静脉OTA升级文件大小*/ 
static uint32_t ota_File_Size = 0; 

/* 指静脉OTA流程状态 */
static FingerveinOtaProcess_enum_t fingervein_OTA_Status = FVN_OTA_INIT;


/* 指静脉模块指令码 */ 
#define CMD_HELLO			0X35
#define CMD_START_OTA  		0X56

/* 指静脉模块ACK确认码  */
#define FINGERVEIN_RES_SUCCESS              0X00   //成功
#define FINGERVEIN_RES_FAILE                0X01   //失败
#define FINGERVEIN_RES_TIMEOUT              0X26   //超时错误

#define TX_RES_TIMEOUT               0XFF   //MCU发送操作超时
#define TX_RES_OK            		 0XAA   //MCU发送正常，并已收到指静脉的回复包；

// 不同指令的超时时间
#define NORMAL_CMD_TIMEOUT 			1500							//一般指令超时时间，
#define HELLO_CMD_TIMEOUT 			500								//握手指令超时时间
#define OTA_CMD_TIMEOUT				200000							



/************************************【START】指静脉串口发送和接收数据结构体定义***************************************/
#define HELLO_OK				  0X55		  //指静脉模组的就绪握手信号，每次启动完成后上报；
#define PROTOCOL_STX              0xEF01      //帧数据头
#define CHIPADDR                  0xFFFFFFFF  //芯片地址

#define PACK_TYPE_CMD    		  0X01        //包类型：命令包，MCU --> Fingervein
#define PACK_TYPE_DATA            0X02	      //包类型：数据包，且有后续包，Fingervein --> MCU
#define PACK_TYPE_DATA_END        0X08	      //包类型：最后一个数据包，即结束包，Fingervein --> MCU
#define PACK_TYPE_ACK             0X07	      //包类型：应答包，Fingervein --> MCU

/*功能函数宏定义*/
#define CHECK_SUM_DATA_START      6           //计算校验和时，数据起始位相对数据帧首字节的偏移位数
#define CHECK_SUN_LEN_ADD         1	          //计算校验和时，计算长度相对帧数据长度增加的个数

//TODO
#define MAX_CMD_PACKAGE_LEN        64          		//指静脉指令包最大包长
#define MAX_TX_PACKAGE_LEN        550          		//指静脉发送最大包长（PS：指静脉OTA升级时，升级数据分包大小为512个字节）
#define MAX_RX_PACKAGE_LEN        128         		//指静脉接收最大包长

#define MAX_CMD_PARAM_LEN			10			//指静脉指令码的最大参数长度；

#pragma pack(1)

/* 锁发送命令给指静脉模组消息结构 */
typedef struct
{
	FingerveinMessageCallback_fun_t cb;
	uint8_t cmd;
	uint16_t dataLen;
	uint32_t timeout;
	uint8_t dataBuf[MAX_CMD_PACKAGE_LEN];
} FingerveinTxCmdMsg_stu_t;


/*帧头数据结构*/
typedef struct
{
	uint16_t stx;                               //帧头
	uint32_t chipAddr;                          //芯片地址
	uint8_t msgType;                            //帧标识
	uint16_t dataLen;                           //data数据长度
} ProtocolDataHead_stu_t;

/*帧数据结构*/
typedef struct
{
	ProtocolDataHead_stu_t head;                //帧头结构体
	uint8_t data[];				                      //命令
} CmdPacket_stu_t;

/*指静脉命令参数据结构*/
typedef struct
{
	uint8_t cmd;                					//指令码
	uint8_t param[];				                //指令参数，长度不定
} CmdParamPacket_stu_t;

#pragma pack()

//发送包信息
static struct
{
	uint8_t dataBuf[MAX_TX_PACKAGE_LEN];      		//当前发送的整包数据
	uint16_t dataLen;		                      	//当前发送数据的总长度

	uint8_t cmd;			                        //发送的命令
	uint8_t sendCnt;			                    //发送次数计数
	FlagStatus waitAckFlag;	                  		//等待ack标志位
	uint32_t timeStamp;		                    	//时间戳
	uint32_t waitAckTimeout;                  		//等待超时时间
	enum
	{					 
		TX_STA_IDLE,	  
		TX_STA_WAIT_ACK, 
    	TX_STA_WAIT_NEXT
	} status;
} CmdPacketTxInfo;

//接收包信息
static struct
{
	uint8_t protocolBuf[MAX_RX_PACKAGE_LEN]; 			//协议buff
	uint8_t protocolCount;				  		      	//协议计数

} CmdPacketRxInfo;
/************************************【END】指静脉串口发送和接收数据结构体定义**************************************/

/*********指静脉操作指令对应函数*********/
static void Fingervein_Cmd_Hello(void);						//指静脉握手指令：35H
static void Fingervein_Cmd_StartOta(uint32_t fileLen);		//指静脉开始OTA指令：56H
/********************************************/ 




/**
  * @brief  指静脉OTA启动
  * @note   
  *         
  * @param  
  */
static ErrorStatus Fingervein_OTA_Start(uint32_t fileLen)
{
	//给模组上电
	FINGERVEIN_TASK_LOG("Fingervein module power on\r\n");
	FINGERVEIN_MODULE_POWER_ON;
	module_PowerOn_Flag = SET;
	/* 创建指静脉模块定时同步握手事件 */
	OSAL_EventSingleCreate(COMP_FINGERVEIN_OTA, EVENT_SYNC_WITH_MODULE, 1200, EVT_PRIORITY_MEDIUM);
	
	/* 创建定时处理指静脉协议事件 */
	// OSAL_EventRepeatCreate(COMP_FINGERVEIN_OTA, EVENT_FINGERVEIN_PROTOCOL, 10, EVT_PRIORITY_MEDIUM);

	ota_File_Size = fileLen;
	FINGERVEIN_TASK_LOG("ota_File_Size = %d\r\n", fileLen);
	if (ota_rbHandle == NULL)
	{
		//先创建一个环形缓存存储应用层发送过来的OTA升级数据；
		ota_rbHandle = OSAL_RingBufferCreate(FINGERVEIN_OTA_RINGBUFF_NUM, FINGERVEIN_OTA_RINGBUFF_SIZE);
	}

	//发送OTA升级指令
	Fingervein_Cmd_StartOta(fileLen);

	fingervein_OTA_Status = FVN_OTA_WAIT_CMD_ACK;

    return SUCCESS;
}

/**
  * @brief  从应用层分包接收OTA文件内容，存入环形缓存里面做中转
  * @note   给应用层调用的API函数
  *         
  * @param  data:分包数据
  */
static ErrorStatus Fingervein_Recv_OTA_FileData(Fingervein_OTA_DataPacket *pdata)
{
	uint32_t ringbuffLen = 0;
	uint8_t tmpData = 0;


    if(ota_rbHandle != NULL)
    {
        __FINGERVEIN_TASK_DEBUG_LOG("recv OTA packet, psn = %d,size = %d\r\n",pdata->psn, pdata->size);
		ringbuffLen = OSAL_RingBufferGetValidSize(ota_rbHandle);
		__FINGERVEIN_TASK_DEBUG_LOG("ringbuffDataLen = %d\r\n", ringbuffLen);
        if((FINGERVEIN_OTA_RINGBUFF_NUM - ringbuffLen) < pdata->size)		//OTA存储的环形缓存剩余长度小于分包的长度，返回失败
        {
            return ERROR;
        }
        else
        {
			for (uint32_t i = 0; i < pdata->size; i++)
			{
				tmpData = pdata->data[i];
				if (OSAL_RingBufferWrite(ota_rbHandle, &tmpData) != SUCCESS)			//单字节写入
				{
					FINGERVEIN_TASK_LOG("Fingervein ota_rbHandle write err\r\n");
					return ERROR;
				}
			}
			__FINGERVEIN_TASK_DEBUG_LOG("OTA packet ringbuff write finish\r\n");
			return SUCCESS;
        }
    }
}


static ErrorStatus Fingervein_SendPacket(uint8_t packType, uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag);

#define OTA_TX_PACK_SIZE 			256					//每个OTA发送包的数据长度
#define OTA_TX_SECTION_SIZE			(32*1024)			//OTA发送数据段的分割大小，每收到一个数据段，指静脉模块返回一个ACK；
/**
  * @brief  从环形缓存里面取数据，分包发送OTA文件内容给指静脉模组，
  * @note   
  *         
  * @param  
  */
static void Fingervein_Send_OTA_FileData(void)
{
	FingerveinOTAMsg_t ota_Result_Msg;
	static uint32_t otaTotalSectionSendcnt = 0;		//已累计发送的分段OTA字节数，不累加当前正在发送的分段字节数
	static uint32_t otaSectionSentCnt = 0;			//当前分段发送中，已发送的OTA字节数
	static sendCnt = 0;		
	uint8_t tmpData = 0, packType = 0;
	uint32_t dataLen = 0;
	FlagStatus ack_Flag;
	uint8_t dataBuff[OTA_TX_PACK_SIZE] = {0};

	if ((ota_File_Size - otaTotalSectionSendcnt) > OTA_TX_SECTION_SIZE)	//剩余发送字节大于分段字节数，按整段发送
	{
		dataLen = ((OTA_TX_SECTION_SIZE - otaSectionSentCnt) > OTA_TX_PACK_SIZE ) ? OTA_TX_PACK_SIZE : (OTA_TX_SECTION_SIZE - otaSectionSentCnt);
	}
	else
	{
		dataLen = ((ota_File_Size - otaTotalSectionSendcnt - otaSectionSentCnt) > OTA_TX_PACK_SIZE ) ? OTA_TX_PACK_SIZE : (ota_File_Size - otaTotalSectionSendcnt - otaSectionSentCnt);
	}

	FINGERVEIN_TASK_LOG("dataLen = %d\r\n", dataLen);
	if (OSAL_RingBufferGetValidSize(ota_rbHandle) < dataLen)			//环形缓存的可读数据长度小于包长度；
	{
		FINGERVEIN_TASK_LOG("OTA ringbuff data is not enough\r\n");
		return;
	}
	
	for (uint32_t i = 0; i < dataLen; i++)
	{
		if (OSAL_RingBufferRead(ota_rbHandle, &tmpData) != SUCCESS)			//单字节读取
		{
			FINGERVEIN_TASK_LOG("Fingervein OTA_rbHandle read err\r\n");
			//TODO如果连续多次读取不到数据，要做超时处理；
		}
		dataBuff[i]	= tmpData;
	}

	otaSectionSentCnt += dataLen;
	sendCnt++;
	FINGERVEIN_TASK_LOG("filesize = %d, sendCnt = %d,otaSectionSentCnt = %d, otaTotalSectionSendcnt = %d\r\n", ota_File_Size, sendCnt, otaSectionSentCnt, otaTotalSectionSendcnt);

	if (otaSectionSentCnt % 1024 == 0)		//1K字节返回一个ack
	{
		//上报OTA准备完毕
		ota_Result_Msg.ota_Result = FINGERVEIN_OTA_READY;
		OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg));
	}
	

	if (otaTotalSectionSendcnt + otaSectionSentCnt == ota_File_Size)
	{
		packType = PACK_TYPE_DATA_END;			//数据结束包；
		ack_Flag = SET;
		// 整个文件发送完成，删除OTA事件，停止发送，等待模组的回复
		OSAL_EventDelete(COMP_FINGERVEIN_OTA, EVENT_OTA_START);

		fingervein_OTA_Status = FVN_OTA_SEND_ALL_FILE_FINISH;
		FINGERVEIN_TASK_LOG("OTA send all file finish ,wait for ack\r\n");
	}
	else
	{
		if (otaSectionSentCnt == OTA_TX_SECTION_SIZE)
		{
			packType = PACK_TYPE_DATA_END;			//数据结束包；
			ack_Flag = SET;
			otaTotalSectionSendcnt += otaSectionSentCnt;
			otaSectionSentCnt = 0;

			//分段文件发送完成，删除OTA事件，暂停发送，等待模组的回复
			OSAL_EventDelete(COMP_FINGERVEIN_OTA, EVENT_OTA_START);

			fingervein_OTA_Status = FVN_OTA_SEND_SECTION_FILE_FINISH;
			FINGERVEIN_TASK_LOG("OTA send section file finish ,wait for ack\r\n");
		}
		else
		{
			packType = PACK_TYPE_DATA;			//数据包；
			ack_Flag = RESET;
		}	
	}

	if (Fingervein_SendPacket(packType, CMD_START_OTA, dataBuff, dataLen, ack_Flag) != SUCCESS)
	{
		FINGERVEIN_TASK_LOG("Fingervein OTA SendPacket failed\r\n");
	}

	return;
}


/**
  * @brief 创建指静脉数据读取缓冲区队列
  *
  * @note 
  */
static void Fingervein_CreateRingBuffHandle(void)
{
	if (fingerveinTx_rbHandle == NULL)
	{
		fingerveinTx_rbHandle = OSAL_RingBufferCreate(FINGERVEIN_TX_RINGBUFF_NUM, sizeof(FingerveinTxCmdMsg_stu_t));
	}
	if (fingerveinRx_rbHandle == NULL)
	{
		fingerveinRx_rbHandle = OSAL_RingBufferCreate(FINGERVEIN_RX_RINGBUFF_NUM, FINGERVEIN_RX_RINGBUFF_SIZE);
	}
	if (operate_rbHandle == NULL)
	{
		operate_rbHandle = OSAL_RingBufferCreate(FINGERVEIN_OPERATE_RINGBUFF_NUM, sizeof(FingerveinTxCmdMsg_stu_t));
	}
}

/**
  * @brief   指静脉串口回调函数
  * @details 详细说明：
  *         
  * @param[in]  dev：
  * @param[in]  data：
  * @param[in]  len：
  * 
  * @return       NULL
  */
static void Fingervein_ReceiveCb(VirtualHardware_enum_t dev, void *data, uint32_t len)
{
	if (fingerveinRx_rbHandle == NULL)
	{
		return;
	}
	for (uint32_t i = 0; i < len; i++)
	{
		uint8_t tmp = ((uint8_t *)data)[i];
		if (OSAL_RingBufferWrite(fingerveinRx_rbHandle, &tmp) != SUCCESS)
		{
			FINGERVEIN_TASK_LOG("Fingervein ringbuff write err\r\n");
			return;
		}
	}
}

/**
  * @brief  指静脉中断处理
  * @note   
  * @return 
  */
static void Fingervein_Int_Irq_Handler(char *name, uint8_t status, uint8_t times)
{

}

/**
  * @brief  指静脉协议初始化
  *
  * @note
  */
static void Fingervein_ProtocolInit()
{
	CmdPacketTxInfo.status = TX_STA_IDLE;

}

/**
  * @brief 清除指静脉发送和设置缓存数据
  *
  * @note  
  */
static void Fingervein_ResetRingBuffData(void)
{
	OSAL_RingBufferReset(fingerveinTx_rbHandle);
	OSAL_RingBufferReset(fingerveinRx_rbHandle);
	OSAL_RingBufferReset(operate_rbHandle);
}

/**
  * @brief  计算校验和
  * @note
  *
  * @param  pData: 数据指针
  * @param  len: 数据长度
  * @return 数据校验和:

  */
static uint16_t Fingervein_CalcCheckSum(uint8_t *pData, uint16_t len)
{
	uint16_t sum = 0;
	for (; len; len--)
	{
		sum += *pData++;
	}
	return sum;
}


/**
  * @brief  从底层环形缓存获取一包数据并解析
  *
  * @note   底层驱动收到数据，会暂存在环形缓存区
  *
  * @return 返回解析后的数据包地址，解析失败返回NULL
  */
static uint8_t *Fingervein_GetOnePacket(void)
{
	static uint8_t getPacketTimeoutCnt = 0;
	uint8_t *protocolBuff = NULL;                               //临时指针，数据接收解析时，指向CmdPacketRxInfo的解析数据缓存
	uint8_t *pCnt = NULL;                                       //临时指针，数据接收解析时，指向CmdPacketRxInfo的解析计数
	uint16_t CalcSum = 0;										//实际计算的校验和
	uint16_t recvSum = 0;										//收到的数据帧中的校验和
	static uint16_t packetLen = 0;                              //整包长度
	uint8_t tmpData;                                            //缓冲变量，从缓冲区读数据
	uint32_t tmpLen = 0;                                        //缓冲变量，从缓冲区读取数据的长度
	ProtocolDataHead_stu_t *pPacketHead = NULL;
	uint8_t buff[64];

	//查询缓冲区是否有数据
	tmpLen = OSAL_RingBufferGetValidSize(fingerveinRx_rbHandle);
	if (tmpLen == 0)
	{
		/* 连续3次没有读取到数据（30ms） */
		if (++getPacketTimeoutCnt >= 3)
		{
			if(CmdPacketRxInfo.protocolCount)
			{
				FINGERVEIN_TASK_LOG("fingervein recv timeout\r\n");
			}
			getPacketTimeoutCnt = 0;
			CmdPacketRxInfo.protocolCount = 0;                      //清0解析计数
			packetLen = 0;											//清0解析包长度
		}
	  return NULL;
	}

	pCnt = &(CmdPacketRxInfo.protocolCount);	                  //解析计数
	protocolBuff = CmdPacketRxInfo.protocolBuf;                 //解析缓存
	pPacketHead = (ProtocolDataHead_stu_t *)protocolBuff;

	// __FINGERVEIN_TASK_DEBUG_LOG("Uart Fingervein RX Len = %d\r\n", tmpLen);
	for (; tmpLen; tmpLen--)                                    //循环读字节
	{
		OSAL_RingBufferRead(fingerveinRx_rbHandle, &tmpData);   //读取到一个字节数据
		// __FINGERVEIN_TASK_DEBUG_LOG(" %02X", tmpData);
		if(*pCnt == 0)
		{
			if (tmpData == (PROTOCOL_STX >> 8))        //帧数据头高字节
			{
				protocolBuff[0] = tmpData;
				*pCnt = 1;  
			}
			else if (tmpData == HELLO_OK)
			{
				protocolBuff[0] = tmpData;
				*pCnt = 0;
				return protocolBuff;

			}
		}
		else if(*pCnt == 1)
		{
			if (tmpData == (PROTOCOL_STX & 0x00FF))                 //帧数据头低字节
			{
				protocolBuff[1] = tmpData;
				*pCnt = 2;
			}
    	}
		else if(*pCnt > 1)
		{
			protocolBuff[*pCnt] = tmpData;
			*pCnt = *pCnt + 1;
			if(*pCnt == 9)
			{
				// 不需要大小端转换
				// FINGERVEIN_TASK_LOG("datalen %04x, %04x", pPacketHead->dataLen,pPacketHead->stx);
				// packetLen = pPacketHead->dataLen + 9;  //包总长，data + 包头(2) + chipAddr(4) + msgType(1) + dataLen(2)
				packetLen = pPacketHead->dataLen;
				packetLen = SWAP16(packetLen) + 9;
				// FINGERVEIN_TASK_LOG("packetLen = %d\r\n", packetLen);
			}
			if(packetLen == *pCnt)
			{
				CalcSum = Fingervein_CalcCheckSum(protocolBuff + CHECK_SUM_DATA_START, (uint8_t)(packetLen - 9) + CHECK_SUN_LEN_ADD);
				// FINGERVEIN_TASK_LOG("Uart Fingervein CalcSum = %#x", CalcSum);
				recvSum = ((protocolBuff[packetLen - 2]) << 8) + protocolBuff[packetLen - 1];			//2bytes的校验和，高字节在前低字节在后
				// FINGERVEIN_TASK_LOG("Uart Fingervein recvSum = %#x", recvSum);
				if (recvSum == CalcSum) 	//判断校验和
				{
					FINGERVEIN_TASK_DEBUG_LOG("\r\n");
					__FINGERVEIN_TASK_DEBUG_LOG("FingerveinTask Receive:");
					for (int i = 0; i < packetLen; i++)
					{
						__FINGERVEIN_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
					}
					__FINGERVEIN_TASK_DEBUG_LOG("\r\n");
					*pCnt = 0;
					packetLen = 0;											//清0解析包长度
					return protocolBuff;
				}
				else
				{
					FINGERVEIN_TASK_LOG("CRC ERR!FingerveinTask Receive:");
					for (int i = 0; i < packetLen; i++)
					{
						__FINGERVEIN_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
					}
					__FINGERVEIN_TASK_DEBUG_LOG("\r\n");
					*pCnt = 0;
					packetLen = 0;											//清0解析包长度
					return NULL;
				}			
			}
		}
	}
	return NULL;
}



/**
  * @brief  发消息给队列
  *
  * @param  cmd：命令
  * @param  pData：数据域指针
  * @param  dataLen：数据长度
  * @param  cb：reply回调函数
  */
static void Fingervein_SendCmdToRingBuff(uint8_t cmd, uint8_t *pData, uint16_t dataLen, FingerveinMessageCallback_fun_t cb, uint32_t timeout)
{
	FingerveinTxCmdMsg_stu_t msgTxData;
	msgTxData.cmd = cmd;
	msgTxData.cb = cb;
	msgTxData.timeout = timeout;
	msgTxData.dataLen = dataLen;
	memcpy(msgTxData.dataBuf, pData, dataLen);
	if (cmd == CMD_HELLO)			//握手命令做一个特殊处理
	{
		if (operate_rbHandle != NULL)
		{
			if (OSAL_RingBufferWrite(operate_rbHandle, &msgTxData) == ERROR)
			{
				FINGERVEIN_TASK_LOG("operate_rbHandle RingBuffer Write error cmd = %#x\r\n", cmd);
			}
		}
	}
	else
	{
		if (fingerveinTx_rbHandle != NULL)
		{
			// FINGERVEIN_TASK_LOG("fingerveinTx_rbHandle Write cmd = %#x\r\n", cmd);
			if (OSAL_RingBufferWrite(fingerveinTx_rbHandle, &msgTxData) == ERROR)
			{
				FINGERVEIN_TASK_LOG("fingerveinTx_rbHandle RingBuffer Write error cmd = %#x\r\n", cmd);
			}
		}
	}
}


/**
  * @brief 指静脉的握手命令回调处理函数
  * @note
  * @param
  * @return
  */
static void Fingervein_Cmd_Hello_Callback(uint8_t result, uint8_t *data, uint8_t len)
{
	FingerveinOTAMsg_t ota_Result_Msg;
	if (result == TX_RES_TIMEOUT)		//指静脉握手命令超时
	{
		CmdPacketTxInfo.status = TX_STA_IDLE;
		module_Ready_Flag = RESET;

		//上报OTA失败
		ota_Result_Msg.ota_Result = FINGERVEIN_OTA_ERROR;
		OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg)); 
		
		return;
	}
	

	if (data[0] == FINGERVEIN_RES_SUCCESS)
	{
		FINGERVEIN_TASK_LOG("Fingervein Hello OK\r\n");
		CmdPacketTxInfo.status = TX_STA_IDLE;
		module_Ready_Flag = SET;
	}
	else if(data[0] == FINGERVEIN_RES_FAILE) 
	{
		FINGERVEIN_TASK_LOG("Fingervein Hello faild\r\n");

		//上报OTA失败
		ota_Result_Msg.ota_Result = FINGERVEIN_OTA_ERROR;
		OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg)); 
	}
	
	return;
}




/**
  * @brief 指静脉OTA命令回调处理函数
  * @note
  * @param
  * @return
  */
static void Fingervein_Cmd_OTA_Callback(uint8_t result, uint8_t *data, uint8_t len)
{
	FingerveinOTAMsg_t ota_Result_Msg;
	if (result == TX_RES_TIMEOUT)
	{
		CmdPacketTxInfo.status = TX_STA_IDLE;
		return;
	}

	FINGERVEIN_TASK_LOG("fingervein_OTA_Status = %d\r\n", fingervein_OTA_Status);
	switch (fingervein_OTA_Status)
	{
		case FVN_OTA_WAIT_CMD_ACK:
			if (data[0] == FINGERVEIN_RES_SUCCESS)
			{
				FINGERVEIN_TASK_LOG("Cmd_OTA:Res = success\r\n");
				//上报OTA准备完毕
				ota_Result_Msg.ota_Result = FINGERVEIN_OTA_START;
				OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg));

				/* 创建指静脉模块OTA事件，进行文件数据发送 */
				OSAL_EventRepeatCreate(COMP_FINGERVEIN_OTA, EVENT_OTA_START, 55, EVT_PRIORITY_MEDIUM);
				fingervein_OTA_Status = FVN_OTA_SENDING_SECTION_FILE;
			}
			else
			{
				FINGERVEIN_TASK_LOG("Cmd_OTA:Res = failed,errorCode = %#x\r\n", data[0]);
				CmdPacketTxInfo.status = TX_STA_IDLE;
				//上报OTA失败
				ota_Result_Msg.ota_Result = FINGERVEIN_OTA_ERROR;
				OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg)); 
			}
		break;

		case FVN_OTA_SEND_SECTION_FILE_FINISH:
			if (data[0] == FINGERVEIN_RES_SUCCESS)
			{
				FINGERVEIN_TASK_LOG("send ota section file ack :Res = success\r\n");
				/* 创建指静脉模块OTA事件，进行文件数据发送 */
				OSAL_EventRepeatCreate(COMP_FINGERVEIN_OTA, EVENT_OTA_START, 55, EVT_PRIORITY_MEDIUM);
				fingervein_OTA_Status = FVN_OTA_SENDING_SECTION_FILE;
			}
			else
			{
				FINGERVEIN_TASK_LOG("send ota section file ack :Res = failed,errorCode = %#x\r\n", data[0]);
				//上报OTA失败
				ota_Result_Msg.ota_Result = FINGERVEIN_OTA_ERROR;
				OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg)); 
			}
		break;

		case FVN_OTA_SEND_ALL_FILE_FINISH:
			if (data[0] == FINGERVEIN_RES_SUCCESS)
			{
				FINGERVEIN_TASK_LOG("send ota all file ack :Res = success\r\n");
				//上报OTA成功
				ota_Result_Msg.ota_Result = FINGERVEIN_OTA_SUCCESS;
				OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg)); 
			}
			else
			{
				FINGERVEIN_TASK_LOG("send ota section file ack :Res = failed,errorCode = %#x\r\n", data[0]);
				//上报OTA失败
				ota_Result_Msg.ota_Result = FINGERVEIN_OTA_ERROR;
				OSAL_MessagePublish(&ota_Result_Msg, sizeof(ota_Result_Msg)); 
			}
		break;

		default:
			break;
	}
	return;	
}


/**
  * @brief  指静脉CMD结果回调
  * @param  result：结果
  * @param  data：返回的数据
  * @param  len: 数据长度
  * @note
  */
static void Fingervein_Cmd_Callback(uint8_t cmd, uint8_t result, uint8_t *data, uint8_t len)
{
	switch (cmd)
	{
		case CMD_HELLO:
			Fingervein_Cmd_Hello_Callback(result, data, len);
		break;

		case CMD_START_OTA:
			Fingervein_Cmd_OTA_Callback(result, data, len);
		break;

		default:
		break;
	}
}


/**
  * @brief  指静脉握手指令0x35H
  * @note
  *
  * @param  
  */
static void Fingervein_Cmd_Hello(void)
{
	uint8_t param[5] = {0};
	param[0] = CMD_HELLO;
	Fingervein_SendCmdToRingBuff(CMD_HELLO, param, 1, Fingervein_Cmd_Callback, HELLO_CMD_TIMEOUT);
}




/**
  * @brief  指静脉开始OTA指令：56H
  * @note   
  *
  * @param  
  */
static void Fingervein_Cmd_StartOta(uint32_t fileLen)
{
	FINGERVEIN_TASK_LOG("Fingervein send Cmd_StartOta = %#X\r\n", CMD_START_OTA);
	uint8_t CmdParamBuff[sizeof(CmdParamPacket_stu_t) + MAX_CMD_PARAM_LEN] = {0};
	uint8_t buffLen = 0;
	CmdParamPacket_stu_t *pCmdBuff = (CmdParamPacket_stu_t *)CmdParamBuff;
	pCmdBuff->cmd = CMD_START_OTA;
	buffLen++;							//1byte指令代码
	pCmdBuff->param[0] = fileLen >> 24;
	buffLen++;							//4byte OTA文件大小，高字节
	pCmdBuff->param[1] = fileLen >> 16;
	buffLen++;							//4byte OTA文件大小
	pCmdBuff->param[2] = fileLen >> 8;
	buffLen++;							//4byte OTA文件大小
	pCmdBuff->param[3] = fileLen >> 0;
	buffLen++;							//4byte OTA文件大小，低字节
	Fingervein_SendCmdToRingBuff(CMD_START_OTA, CmdParamBuff, buffLen, Fingervein_Cmd_Callback, OTA_CMD_TIMEOUT);
}



/**
  * @brief  解析读取的数据包
  * @note
  *
  * @param  pData:数据包
  */
static void Fingervein_ParseRxPacket(uint8_t *pData)
{
	// 处理指静脉模组启动时主动上0x55的Uart握手信号
	if (0X55 == pData[0])
	{
		module_Ready_Flag = SET;	//指静脉模组上电初始化成功，可以正常通信
		__FINGERVEIN_TASK_DEBUG_LOG("\r\n Fingervein Model is Ready,booting success! \r\n\r\n");
		return;
	}
	
	//TODO 需要先判断收到的包类型，是确认包还是数据包
	uint8_t relyLen = 0;	
	CmdPacket_stu_t *pPacketHead = (CmdPacket_stu_t *)pData;
	relyLen = (uint8_t)(SWAP16(pPacketHead->head.dataLen)) - 2;				//数据帧dataLen的长度包括了2位校验和的长度，所以要减2；注意大小端转换后，会直接改变原来数据的高低字节顺序；
	// FINGERVEIN_TASK_LOG("Fingervein_RxPacket:dataLen = %d\r\n", relyLen);
	

	// 处理指静脉模组返回的数据包，并执行对应的回调操作；
	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK)
	{
		//向回调函数传的是除了PacketHead之外的内容，relyLen指的是除了校验和之外的数据长度
		Fingervein_Cmd_Callback(CmdPacketTxInfo.cmd, TX_RES_OK, pPacketHead->data, relyLen);
	}
	return;
}


/**
  * @brief  打印输出发送的命令包
  *
  * @note   
  */
static void Fingervein_PrintfTxData(uint8_t *pData, uint16_t len)
{
// #if defined(DEBUG_EN)
	uint8_t strBuffer[66 * 3], i;
	if (len > 65)
		return; //格式化数组数量不能超过66*3
	for (i = 0; i < len; i++)
	{
		sprintf((char *)&strBuffer[i * 3], "%02X ", pData[i]);
	}
	sprintf((char *)&strBuffer[i * 3], "%s", "\r\n");
	FINGERVEIN_TASK_LOG("Fingervein send packet:%s", strBuffer);
// #endif
}


/**
  * @brief  加载待发送的数据
  * @note   将要发出的数据，填入发送缓存区
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus Fingervein_LoadingDataToBeSent(uint8_t *pData, uint16_t len)
{
	if (len > 0x7FFF) //直接发
	{
		len &= 0x7FFF;
		Fingervein_PrintfTxData(pData, len);
		Device_Write(VHW_UART_FINGERVEIN, pData, len, 0);
		return SUCCESS;
	}
	return ERROR;
}


/**
  * @brief  重发指令包
  *
  * @note   
  */
static void Fingervein_ResendCmdPacket(void)
{
	uint32_t currentTime = OSAL_GetTickCount();
	uint8_t ret = TX_RES_TIMEOUT;

	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK) //当前状态正在等应答
	{
		if (CmdPacketTxInfo.cmd == CMD_HELLO)		//握手命令做超时重发
		{
			if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
			{
				if (CmdPacketTxInfo.sendCnt >= PROTOCOL_RESEND_TIMES)
				{
					//ERR:超时
					FINGERVEIN_TASK_LOG("wait ack Time out cmd = %#2x,%#2x,%#2x,%#2x", CmdPacketTxInfo.cmd, currentTime, CmdPacketTxInfo.timeStamp, CmdPacketTxInfo.waitAckTimeout);
					if (pCmdCallback != NULL)
					{
						//各指令的对应reply的回调函数进行处理
						pCmdCallback(CmdPacketTxInfo.cmd, ret, NULL, 0);
						pCmdCallback = NULL;
					}
					CmdPacketTxInfo.status = TX_STA_IDLE;
				}
				else
				{
					//发送数据
    				Fingervein_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
					(CmdPacketTxInfo.sendCnt)++;
					CmdPacketTxInfo.timeStamp = currentTime;
				}	
			}
		}
		else			//其余命令暂不做重发机制
		{
			if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
			{
				//ERR:超时
				FINGERVEIN_TASK_LOG("wait ack Time out cmd = %#2x,%#2x,%#2x,%#2x", CmdPacketTxInfo.cmd, currentTime, CmdPacketTxInfo.timeStamp, CmdPacketTxInfo.waitAckTimeout);
				if (pCmdCallback != NULL)
				{
					//各指令的对应reply的回调函数进行处理
					pCmdCallback(CmdPacketTxInfo.cmd, ret, NULL, 0);
					pCmdCallback = NULL;
				}
				CmdPacketTxInfo.status = TX_STA_IDLE;
			}
		}
	}
}

/**
  * @brief  接收数据并解析处理
  *
  * @note   先接收数据再解析数据
  */
static void Fingervein_RxProcess(void)
{
	uint8_t *pData = NULL;
	pData = Fingervein_GetOnePacket(); //得到一包数据并检验校验和
	
    if (pData != NULL)
	{
		Fingervein_ParseRxPacket(pData); //解析数据
	}

	Fingervein_ResendCmdPacket();		 //超时重发命令包
}


/**
  * @brief  指静脉模块 数据打包
  * @note   
  *
  * @param  cmd：消息id
  * @param  pData：数据
  * @param  dataLen：数据长度
  * @param  waitAckFlag：等待回复标志
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus Fingervein_SendPacket(uint8_t packType, uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag)
{
	uint16_t calcSum = 0;
	CmdPacket_stu_t *pCmdPacket = (CmdPacket_stu_t *)CmdPacketTxInfo.dataBuf;
	ErrorStatus ret;

	CmdPacketTxInfo.cmd = cmd;
	CmdPacketTxInfo.waitAckFlag = waitAckFlag;
	CmdPacketTxInfo.sendCnt = 1;
	CmdPacketTxInfo.status = TX_STA_WAIT_ACK;
	CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();

	pCmdPacket->head.stx = PROTOCOL_STX;
	pCmdPacket->head.stx = SWAP16(pCmdPacket->head.stx); //大小端转化
	pCmdPacket->head.chipAddr = CHIPADDR;
	pCmdPacket->head.msgType = packType;
	pCmdPacket->head.dataLen = dataLen + 2;	    //原始data长度 + 最后2位检验和的长度
	pCmdPacket->head.dataLen = SWAP16(pCmdPacket->head.dataLen); //大小端转化
	memcpy(pCmdPacket->data, pData, dataLen);

	calcSum = Fingervein_CalcCheckSum((uint8_t *)&(pCmdPacket->head.stx) + CHECK_SUM_DATA_START, dataLen + 2 + CHECK_SUN_LEN_ADD);
	// FINGERVEIN_TASK_LOG("calcSum = %d", calcSum);
	pCmdPacket->data[dataLen] = (calcSum >> 8);
	pCmdPacket->data[dataLen + 1] = (calcSum & 0X00FF);
	CmdPacketTxInfo.dataLen = sizeof(CmdPacket_stu_t) + dataLen + 2;

	//发送数据
	FINGERVEIN_TASK_LOG("Fingervein_SendPacket, cmd = %#X, packetLen = %d\r\n", CmdPacketTxInfo.cmd, CmdPacketTxInfo.dataLen);
    ret = Fingervein_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);

	return ret;

}

/**
  * @brief 处理指静脉串口发送数据
  *
  * @note  
  */
static void Fingervein_TxProcess(void)
{
	FlagStatus ackFlag;
	FingerveinTxCmdMsg_stu_t TxData = {0};

	if (OSAL_RingBufferGetValidSize(operate_rbHandle) != 0)			//优先处理发送握手指令
	{
		if (CmdPacketTxInfo.status == TX_STA_IDLE)	// 发送状态空闲
		{
			if (OSAL_RingBufferRead(operate_rbHandle, &TxData) == SUCCESS)
			{
				if (TxData.cb != NULL)
				{
					ackFlag = SET;
					//指令对应回复的回调进行赋值
					pCmdCallback = TxData.cb;
					CmdPacketTxInfo.waitAckTimeout = TxData.timeout;
				}
				else
				{
					ackFlag = RESET;
				}
				Fingervein_SendPacket(PACK_TYPE_CMD, TxData.cmd, TxData.dataBuf, TxData.dataLen, ackFlag);
			}
		}
	}
	else if (OSAL_RingBufferGetValidSize(fingerveinTx_rbHandle) != 0)
	{
		if ((CmdPacketTxInfo.status == TX_STA_IDLE) && (module_Ready_Flag == SET))	// 发送状态空闲且已与模组握手成功
		{
			if (OSAL_RingBufferRead(fingerveinTx_rbHandle, &TxData) == SUCCESS)
			{
				if (TxData.cb != NULL)
				{
					ackFlag = SET;
					//指令对应回复的回调进行赋值
					pCmdCallback = TxData.cb;
					CmdPacketTxInfo.waitAckTimeout = TxData.timeout;
				}
				else
				{
					ackFlag = RESET;
				}
				Fingervein_SendPacket(PACK_TYPE_CMD, TxData.cmd, TxData.dataBuf, TxData.dataLen, ackFlag);
				// FINGERVEIN_TASK_LOG("RingBuff_Tx_OK cmd = %#X\r\n", TxData.cmd);
			}
		}
	}
}

/**
  * @brief  指静脉上电后的同步握手
  * @note   
  * @return 
  */
static void Fingervein_Sync_With_Module(void)
{
	//指静脉模块上电后，一定时间内未收到指静脉模块的上报的0x55握手信号；
	if (module_Ready_Flag == RESET)		
	{
		/*MCU主动向模块发送握手信号*/
		Fingervein_Cmd_Hello();
	}
}


/**
  * @brief  指静脉组件初始化
  * @note   
  * @return 
  */
static void Fingervein_Init(void)
{
	if (fingervein_Init_Flag == RESET)
	{
		InputPort_stu_t button_list[] = 
		{
			{"FINGERVEIN_INT", IRQ_VHW_FINGERVEIN, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE}, //中断脚
		};
		/* 注册端口 */
		InputPort_Registered(button_list, OSAL_LENGTH(button_list), Fingervein_Int_Irq_Handler);
		InputPort_EnableProt("FINGERVEIN_INT");

		/* 创建环形缓存 */
		Fingervein_CreateRingBuffHandle();
        OSAL_EventRepeatCreate(COMP_FINGERVEIN_OTA, EVENT_FINGERVEIN_PROTOCOL, 10, EVT_PRIORITY_MEDIUM);

		fingervein_Init_Flag = SET;
	}

	/* 注册指静脉串口回调函数 */
	Device_RegisteredCB(VHW_UART_FINGERVEIN, Fingervein_ReceiveCb);
	// 使能指静脉的串口
	Device_Enable(VHW_UART_FINGERVEIN);

	/* 指静脉协议初始化 */
	Fingervein_ProtocolInit();

	/* 注册对外开放的API接口,*/
	SYS_API(Fingervein_OTA_Start);
	SYS_API(Fingervein_Recv_OTA_FileData);
}



/**
  * @brief  Fingervein_Task指静脉任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         3.任务函数必须添加到osal_config.h文件里面
  *
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Fingervein_OTA_Task(uint32_t event)
{
	if (event & EVENT_SYS_START) //任务启动
	{
		FINGERVEIN_TASK_LOG("Fingervein task start\r\n");
		/* 指静脉组件初始化*/
		Fingervein_Init();

		return (event ^ EVENT_SYS_START);
	}

	/* 系统中断事件 */
    if (event & EVENT_SYS_ISR)
    {
        return ( event ^ EVENT_SYS_ISR );
    }


	/* 指静脉串口协议事件 */
	if (event & EVENT_FINGERVEIN_PROTOCOL)
	{
		/* 指静脉串口接收数据处理 */
		Fingervein_RxProcess();

		/* 指静脉串口发送数据处理 */
		Fingervein_TxProcess();
		return (event ^ EVENT_FINGERVEIN_PROTOCOL);
	}


	/*指静脉模块上电后，进行同步握手的事件*/
    if (event & EVENT_SYNC_WITH_MODULE)
    {
		Fingervein_Sync_With_Module();
        return ( event ^ EVENT_SYNC_WITH_MODULE );
    }


	/*指静脉OTA事件*/
    if (event & EVENT_OTA_START)
    {
		Fingervein_Send_OTA_FileData();
        return ( event ^ EVENT_OTA_START );
    }
	

	/* 休眠处理 */
	if (event & EVENT_SYS_SLEEP)
	{
		return (event ^ EVENT_SYS_SLEEP);
	}


	return 0;
}
COMPONENT_TASK_EXPORT(COMP_FINGERVEIN_OTA, Fingervein_OTA_Task, 0);

#endif

